Function New-XmlDocument
{
    Param(
        [Parameter(Mandatory = $True, ValueFromPipeline = $True)]
        [HashTable]
        $private:Data
    )
    
    Process
    {
        Function Append-XmlElement(
            [System.Xml.XmlDocument] $private:XmlDocument, 
            [System.Xml.XmlNode] $private:XmlNode, 
            [HashTable] $private:HashTable)
        {
            $private:XmlElement = $XmlDocument.CreateElement($HashTable.Name)
            
            If ($HashTable.Attributes -Ne $Null)
            {
                ForEach ($private:Attribute in $HashTable.Attributes.GetEnumerator())
                {
                    If ($Attribute -Ne $Null)
                    {
                        $XmlElement.SetAttribute($Attribute.Name, $Attribute.Value)
                    }
                }
            }
            
            If ($HashTable.Value -Ne $Null)
            {
                If ($HashTable.Value -Is [String])
                {
                    $private:XmlText = $XmlDocument.CreateTextNode($HashTable.Value)
                    $XmlElement.AppendChild($XmlText) | Out-Null
                }
                ElseIf ($HashTable.Value -Is [System.Xml.XmlElement])
                {
                    $private:ImportedXmlNode = $XmlDocument.ImportNode($HashTable.Value, $True)
                    $XmlElement.AppendChild($ImportedXmlNode) | Out-Null
                }
                ElseIf ($HashTable.Value -Is [HashTable])
                {
                    If ($HashTable.Value.Count -Gt 0)
                    {
                        Append-XmlElement $XmlDocument $XmlElement $HashTable.Value
                    }
                }
                ElseIf ($HashTable.Value -Is [Array])
                {
                    ForEach ($private:ChildElement in $HashTable.Value)
                    {
                        If (($ChildElement -Ne $Null) -And ($ChildElement.Count -Gt 0))
                        {
                            Append-XmlElement $XmlDocument $XmlElement $ChildElement
                        }
                    }
                }
            }
            
            $XmlNode.AppendChild($XmlElement) | Out-Null
        }
        
        $private:XmlDocument = New-Object System.Xml.XmlDocument
        
        $private:XmlDeclaration = $XmlDocument.CreateXmlDeclaration("1.0", $Null, $Null)
        $XmlDocument.InsertBefore($XmlDeclaration, $XmlDocument.DocumentElement) | Out-Null
        
        Append-XmlElement $XmlDocument $XmlDocument $Data
        
        Return $XmlDocument
    }
}

Export-ModuleMember New-XmlDocument
